#include "slanEditWidget.h"
#include <QFileInfo>
#include <QDebug>
#include <QWidget>
#include <Qsci/qsciscintilla.h>
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
#include <QCloseEvent>

#include <Qsci/qscilexercpp.h>
#include <Qsci/qscilexerpascal.h>
#include<Qsci/qscilexerbash.h>
#include<Qsci/qscilexercsharp.h>
#include<Qsci/qscilexercss.h>
#include<Qsci/qscilexerhtml.h>
#include<Qsci/qscilexerjava.h>
#include<Qsci/qscilexerjavascript.h>
#include<Qsci/qscilexerlua.h>
#include<Qsci/qscilexerpython.h>
#include<Qsci/qscilexerperl.h>
#include<Qsci/qscilexerruby.h>
#include<QSci/qscilexersql.h>
#include<Qsci/qscilexerxml.h>
#include<Qsci/qscilexeryaml.h>
#include<Qsci/qscilexertcl.h>


SlanEditWidget::SlanEditWidget(QWidget *parent)
    : QsciScintilla(parent)
{
    isUntitled = true;
    curLexer = NULL;

    actionFocus = new QAction(this);
    actionFocus->setCheckable(true);
    setUtf8(true);

    connect(actionFocus, &QAction::triggered, this, &SlanEditWidget::show);
    connect(actionFocus, SIGNAL(triggered()), this, SLOT(setFocus()));
//    connect(actionFocus, &QAction::triggered, this, &SlanEditWidget::setFocus);
//    QsciScintilla *textEdit = new QsciScintilla(parent);


}

void SlanEditWidget::newFile()
{
    isUntitled = true;
    static int sequenceNumber = 1;
    curFileName = tr("new_%1").arg(sequenceNumber++);

    setTitle();
    setWindowModified(false);
    connect(this, &SlanEditWidget::textChanged,
            this, &SlanEditWidget::documentWasModified);
}

void SlanEditWidget::setTitle()
{
    qDebug() << "set Title";

    if ( isWindowModified() )
    {

        setWindowTitle(tr("%1*").arg(strippedName(curFileName)));
    }
    else
    {
        setWindowTitle(strippedName(curFileName));
    }
}

inline QString SlanEditWidget::strippedName(const QString &fileName)
{
    return QFileInfo(fileName).fileName();
}

inline QString SlanEditWidget::userFriendlyCurrentFile()
{
    return strippedName(curFileName);
}

inline void SlanEditWidget::setCurrentFile(const QString &fileName)
{
    curFileName = fileName;
}

inline void SlanEditWidget::setActionText(const QString &txt)
{
    actionFocus->setText(txt);
}

bool SlanEditWidget::save()
{
    if (isUntitled)
        return saveAs();

    return saveFile(curFileName);
}

bool SlanEditWidget::saveAs()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("另存为"), ".");
    if (fileName.isEmpty())
        return false;
    return saveFile(fileName);
}

bool SlanEditWidget::saveFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::WriteOnly))
    {
        QMessageBox::warning(this, "SlanEditor",
            tr("保存文件'%1'失败").arg(curFileName));
        return false;
    }

    if (write(&file))
    {
        file.close();
        isUntitled = false;
        setWindowModified(false);
        setCurrentFile(fileName);
        setActionText(fileName);
        setTitle();
        return true;
    }

    return false;
}

bool SlanEditWidget::openFile(const QString &fileName)
{
    if (fileName.isEmpty())
        return NULL;
    return loadFile(fileName);

}

bool SlanEditWidget::loadFile(const QString &fileName)
{
    QFile file(fileName);

    setCurLexer(getFileLexerStyle(fileName));

    if (!file.open(QIODevice::ReadOnly | QFile::Text))
    {
        QMessageBox::warning(this, "SlanEditor",
            tr("打开文件%1失败").arg(curFileName));
        return false;
    }

    if (read(&file))
    {
        file.close();
        isUntitled = false;
        setModified(false);
        setCurrentFile(fileName);
        setActionText(fileName);
        setTitle();
        setModified(false);
        connect(this, &SlanEditWidget::textChanged,
                this, &SlanEditWidget::documentWasModified);
        return true;
    }
    return false;
}

void SlanEditWidget::documentWasModified()
{
    setWindowModified(this->isModified());
    emit undoAvailable(isUndoAvailable());
    emit redoAvailable(isRedoAvailable());
    setTitle();
}

void SlanEditWidget::closeEvent(QCloseEvent *event)
{
    if (okToContinue())
    {
        event->accept();
    }
    else
        event->ignore();
}

bool SlanEditWidget::okToContinue()
{
    if (isWindowModified())
    {
        int result = QMessageBox::warning(this, tr("SlanEditor"),
                        tr("文件“%1”已被修改,是否保存.\n").arg(userFriendlyCurrentFile()),
                        QMessageBox::Yes | QMessageBox::No |
                        QMessageBox::Cancel);

        if (result == QMessageBox::Yes)
            return save();

        else if (result == QMessageBox::Cancel)
            return false;
    }
    return true;
}


//根据文件的类型设置高亮样式
void SlanEditWidget::setCurLexer(SLexerStyle lexer)
{
    if ( getCurLexerStyle() != lexer )
    {
        delete curLexer;
        switch(lexer)
        {
        case SlanEditWidget::lsPascal:
            curLexer = new QsciLexerPascal();
            break;
        case SlanEditWidget::lsBash:
            curLexer = new QsciLexerBash();
            break;
        case SlanEditWidget::lsCpp:
            curLexer = new QsciLexerCPP();
            break;
        case SlanEditWidget::lsCsharp:
            curLexer = new QsciLexerCSharp();
            break;
        case SlanEditWidget::lsCss:
            curLexer = new QsciLexerCSS();
            break;
        case SlanEditWidget::lsHtml:
            curLexer = new QsciLexerHTML();
            break;
        case SlanEditWidget::lsJava:
            curLexer = new QsciLexerJava();
            break;
        case SlanEditWidget::lsJs:
            curLexer = new QsciLexerJavaScript();
            break;
        case SlanEditWidget::lsLua:
            curLexer = new QsciLexerLua();
            break;
        case SlanEditWidget::lsPerl:
            curLexer = new QsciLexerPerl();
            break;
        case SlanEditWidget::lsPython:
            curLexer = new QsciLexerPython();
            break;
        case SlanEditWidget::lsRuby:
            curLexer = new QsciLexerRuby();
            break;
        case SlanEditWidget::lsSql:
            curLexer = new QsciLexerSQL();
            break;
        case SlanEditWidget::lsTcl:
            curLexer = new QsciLexerTCL();
            break;
        case SlanEditWidget::lsXml:
            curLexer = new QsciLexerXML();
            break;
        case SlanEditWidget::lsYaml:
            curLexer = new QsciLexerYAML();
            break;
        default:
            curLexer = NULL;
        }
        setLexer(curLexer);
    }
//    if(!curLexer)
//        return;



}

//获取文件的类型
SlanEditWidget::SLexerStyle SlanEditWidget::getFileLexerStyle(const QString &fileName)
{
    QFileInfo fi(fileName);
    QString ext= fi.completeSuffix();

    if( ext.compare("pas",Qt::CaseInsensitive)==0 ||
        ext.compare("dpr",Qt::CaseInsensitive)==0 ||
        ext.compare("inc",Qt::CaseInsensitive)==0 )
        return lsPascal;
    else if( ext.compare("sql",Qt::CaseInsensitive)==0 )
        return lsSql;
    else if( ext.compare("cpp",Qt::CaseInsensitive)==0 ||
            ext.compare("c",Qt::CaseInsensitive)==0 ||
            ext.compare("h",Qt::CaseInsensitive)==0 ||
            ext.compare("hpp",Qt::CaseInsensitive)==0 )
        return lsCpp;
    else if( ext.compare("cs",Qt::CaseInsensitive)==0 )
        return lsCsharp;
    else if( ext.compare("css",Qt::CaseInsensitive)==0 )
        return lsCss;
    else if( ext.compare("html",Qt::CaseInsensitive)==0 ||
             ext.compare("htm",Qt::CaseInsensitive)==0 )
        return lsHtml;
    else if( ext.compare("java",Qt::CaseInsensitive)==0 )
        return lsJava;
    else if( ext.compare("js",Qt::CaseInsensitive)==0 )
        return lsJs;
    else if( ext.compare("lua",Qt::CaseInsensitive)==0 )
        return lsLua;
    else if( ext.compare("py",Qt::CaseInsensitive)==0 )
        return lsPython;
    else if( ext.compare("pl",Qt::CaseInsensitive)==0 ||
             ext.compare("prl",Qt::CaseInsensitive)==0 )
        return lsPerl;
    else if( ext.compare("rb",Qt::CaseInsensitive)==0 )
        return lsRuby;
    else if( ext.compare("xml",Qt::CaseInsensitive) ==0 ||
             ext.compare("dprj",Qt::CaseInsensitive)==0 ||
             ext.compare("sln",Qt::CaseInsensitive) ==0 ||
             ext.compare("csproj",Qt::CaseInsensitive)==0 )
        return lsXml;
    else if( ext.compare("yaml",Qt::CaseInsensitive)==0 ||
             ext.compare("yml",Qt::CaseInsensitive)==0 )
        return lsYaml;
    else if( ext.compare("tcl",Qt::CaseInsensitive)==0 )
        return  lsTcl;
    else
        return lsNone;
}

//转换QsciLexer为对应的QsciLexer
SlanEditWidget::SLexerStyle SlanEditWidget::getLexerStyle(QsciLexer &lexer)
{
    if(lexer.inherits("QsciLexerPascal"))
        return lsPascal;
    else if(lexer.inherits("QsciLexerBash"))
        return lsBash;
    else if(lexer.inherits("QsciLexerCPP"))
        return lsCpp;
    else if(lexer.inherits("QsciLexerCSharp"))
        return lsCsharp;
    else if(lexer.inherits("QsciLexerCSS"))
        return lsCss;
    else if(lexer.inherits("QsciLexerHTML"))
        return lsHtml;
    else if(lexer.inherits("QsciLexerJava"))
        return lsJava;
    else if(lexer.inherits("QsciLexerJavaScript"))
        return lsJs;
    else if(lexer.inherits("QsciLexerLua"))
        return lsLua;
    else if(lexer.inherits("QsciLexerPython"))
        return lsPython;
    else if(lexer.inherits("QsciLexerPerl"))
        return lsPerl;
    else if(lexer.inherits("QsciLexerRuby"))
        return lsRuby;
    else if(lexer.inherits("QsciLexerSQL"))
        return lsSql;
    else if(lexer.inherits("QsciLexerXML"))
        return lsXml;
    else if(lexer.inherits("QsciLexerYAML"))
        return lsYaml;
    else if(lexer.inherits("QsciLexerTCL"))
        return lsTcl;
    else
        return lsNone;
}

//获取当前高亮样式
SlanEditWidget::SLexerStyle SlanEditWidget::getCurLexerStyle()
{
    if(curLexer)
    {
        return getLexerStyle(*curLexer);
    }
    else
        return lsNone;
}
